home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / TxtPlayer / BltAlpha.h < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  13.1 KB  |  443 lines

  1. //------------------------------------------------------------------------------
  2. // File: BltAlpha.h
  3. //
  4. // Desc: DirectShow sample code - implementation of CAlphaBlt class.
  5. //
  6. // Copyright (c) 1994 - 2001, Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. #ifndef __INITDDSTRUCT_DEFINED
  11. #define __INITDDSTRUCT_DEFINED
  12. template <typename T>
  13. __inline void INITDDSTRUCT(T& dd)
  14. {
  15.     ZeroMemory(&dd, sizeof(dd));
  16.     dd.dwSize = sizeof(dd);
  17. }
  18. #endif
  19.  
  20. #ifndef __RELEASE_DEFINED
  21. #define __RELEASE_DEFINED
  22. template<typename T>
  23. __inline void RELEASE( T* &p )
  24. {
  25.     if( p ) {
  26.         p->Release();
  27.         p = NULL;
  28.     }
  29. }
  30. #endif
  31.  
  32. #ifndef CHECK_HR
  33.     #define CHECK_HR(expr) do { if (FAILED(expr)) __leave; } while(0);
  34. #endif
  35.  
  36.  
  37. class CAlphaBlt
  38. {
  39. private:
  40.  
  41.     LPDIRECTDRAW7               m_pDD;
  42.     LPDIRECT3D7                 m_pD3D;
  43.     LPDIRECT3DDEVICE7           m_pD3DDevice;
  44.     LPDIRECTDRAWSURFACE7        m_lpDDBackBuffer;
  45.  
  46.     LPDIRECTDRAWSURFACE7        m_lpDDMirror;
  47.     LPDIRECTDRAWSURFACE7        m_lpDDM32;
  48.     LPDIRECTDRAWSURFACE7        m_lpDDM16;
  49.     DDSURFACEDESC2              m_ddsdM32;
  50.     DDSURFACEDESC2              m_ddsdM16;
  51.  
  52.     bool                        m_fPowerOf2;
  53.     bool                        m_fSquare;
  54.  
  55.     //
  56.     // IsSurfaceBlendable
  57.     //
  58.     // Checks the DD surface description and the given
  59.     // alpha value to determine if this surface is blendable.
  60.     //
  61.     bool
  62.     IsSurfaceBlendable(
  63.         DDSURFACEDESC2& ddsd,
  64.         BYTE fAlpha
  65.         )
  66.     {
  67.         //
  68.         // Is the blend really a blend ?
  69.         //
  70.  
  71.         //if (fAlpha == 0 || fAlpha == 255) {
  72.         //    return true;
  73.         //}
  74.  
  75.         //
  76.         // Is the surface already a D3D texture ?
  77.         //
  78.         if (ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
  79.             return true;
  80.         }
  81.  
  82.         //
  83.         // OK we have to mirror the surface
  84.         //
  85.  
  86.         return false;
  87.     }
  88.  
  89.     //
  90.     // MirrorSourceSurface
  91.     //
  92.     // The mirror surface can be either 16 or 32 bit RGB depending
  93.     // upon the format of the source surface.
  94.     //
  95.     // Of course it should have the "texture" flag
  96.     // set and should be in VRAM.  If we can't create the
  97.     // surface then the AlphaBlt should fail
  98.     //
  99.     HRESULT MirrorSourceSurface(
  100.         LPDIRECTDRAWSURFACE7 lpDDS,
  101.         DDSURFACEDESC2& ddsd
  102.         )
  103.     {
  104.         HRESULT hr = DD_OK;
  105.         DWORD dwMirrorBitDepth = 0;
  106.         DDSURFACEDESC2 ddsdMirror={0};
  107.  
  108.  
  109.         //
  110.         // OK - is it suitable for our needs.
  111.         //
  112.         // The following rules apply:
  113.         //  if ddsd is a FOURCC surface the mirror should be 32 bit
  114.         //  if ddsd is RGB then the mirror's bit depth should match that of ddsd.
  115.         //
  116.         // Also, the mirror must be large enough to actually hold
  117.         // the surface to be blended
  118.         //
  119.  
  120.         m_lpDDMirror = NULL;
  121.  
  122.         if (ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ||
  123.             ddsd.ddpfPixelFormat.dwRGBBitCount == 32) {
  124.  
  125.             if (ddsd.dwWidth > m_ddsdM32.dwWidth ||
  126.                 ddsd.dwHeight > m_ddsdM32.dwHeight) {
  127.  
  128.                 RELEASE(m_lpDDM32);
  129.             }
  130.  
  131.             if (!m_lpDDM32) {
  132.                 dwMirrorBitDepth = 32;
  133.             }
  134.             else {
  135.                 m_lpDDMirror = m_lpDDM32;
  136.                 ddsdMirror = m_ddsdM32;
  137.             }
  138.         }
  139.         else if (ddsd.ddpfPixelFormat.dwRGBBitCount == 16) {
  140.  
  141.             if (ddsd.dwWidth > m_ddsdM16.dwWidth ||
  142.                 ddsd.dwHeight > m_ddsdM16.dwHeight) {
  143.  
  144.                 RELEASE(m_lpDDM16);
  145.             }
  146.  
  147.             if (!m_lpDDM16) {
  148.                 dwMirrorBitDepth = 16;
  149.             }
  150.             else {
  151.                 m_lpDDMirror = m_lpDDM16;
  152.                 ddsdMirror = m_ddsdM16;
  153.             }
  154.         }
  155.         else {
  156.  
  157.             // No support for RGB24 or RGB8 !
  158.             return E_INVALIDARG;
  159.         }
  160.  
  161.         if (!m_lpDDMirror) {
  162.  
  163.             INITDDSTRUCT(ddsdMirror);
  164.             ddsdMirror.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  165.             ddsdMirror.ddpfPixelFormat.dwFlags = DDPF_RGB;
  166.             ddsdMirror.ddpfPixelFormat.dwRGBBitCount = dwMirrorBitDepth;
  167.  
  168.             switch (dwMirrorBitDepth) {
  169.             case 16:
  170.                 ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x0000F800;
  171.                 ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x000007E0;
  172.                 ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x0000001F;
  173.                 break;
  174.  
  175.             case 32:
  176.                 ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
  177.                 ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
  178.                 ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x000000FF;
  179.                 break;
  180.             }
  181.  
  182.             ddsdMirror.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
  183.             ddsdMirror.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
  184.  
  185.             if (m_fPowerOf2) {
  186.  
  187.                 for (ddsdMirror.dwWidth = 1;
  188.                      ddsd.dwWidth > ddsdMirror.dwWidth;
  189.                      ddsdMirror.dwWidth <<= 1);
  190.  
  191.                 for (ddsdMirror.dwHeight = 1;
  192.                      ddsd.dwHeight > ddsdMirror.dwHeight;
  193.                      ddsdMirror.dwHeight <<= 1);
  194.             }
  195.             else {
  196.                 ddsdMirror.dwWidth = ddsd.dwWidth;
  197.                 ddsdMirror.dwHeight = ddsd.dwHeight;
  198.             }
  199.  
  200.             if (m_fSquare) {
  201.  
  202.                 if (ddsdMirror.dwHeight > ddsdMirror.dwWidth) {
  203.                     ddsdMirror.dwWidth = ddsdMirror.dwHeight;
  204.                 }
  205.  
  206.                 if (ddsdMirror.dwWidth > ddsdMirror.dwHeight) {
  207.                     ddsdMirror.dwHeight = ddsdMirror.dwWidth;
  208.                 }
  209.             }
  210.  
  211.             __try {
  212.  
  213.                 // Attempt to create the surface with theses settings
  214.                 CHECK_HR(hr = m_pDD->CreateSurface(&ddsdMirror, &m_lpDDMirror, NULL));
  215.  
  216.                 INITDDSTRUCT(ddsdMirror);
  217.                 CHECK_HR(hr =  m_lpDDMirror->GetSurfaceDesc(&ddsdMirror));
  218.  
  219.                 switch (dwMirrorBitDepth) {
  220.                 case 16:
  221.                     m_ddsdM16 = ddsdMirror;
  222.                     m_lpDDM16 = m_lpDDMirror;
  223.                     break;
  224.  
  225.                 case 32:
  226.                     m_ddsdM32 = ddsdMirror;
  227.                     m_lpDDM32 = m_lpDDMirror;
  228.                     break;
  229.                 }
  230.  
  231.             } __finally {}
  232.         }
  233.  
  234.         if (hr == DD_OK) {
  235.  
  236.             //ASSERT(m_lpDDMirror != NULL);
  237.  
  238.             __try {
  239.                 RECT rc = {0, 0, ddsd.dwWidth, ddsd.dwHeight};
  240.                 CHECK_HR(hr = m_lpDDMirror->Blt(&rc, lpDDS, &rc, DDBLT_WAIT, NULL));
  241.                 ddsd = ddsdMirror;
  242.             } __finally {}
  243.         }
  244.  
  245.         return hr;
  246.     }
  247.  
  248. public:
  249.  
  250.     ~CAlphaBlt()
  251.     {
  252.         RELEASE(m_lpDDBackBuffer);
  253.         RELEASE(m_lpDDM32);
  254.         RELEASE(m_lpDDM16);
  255.  
  256.         RELEASE(m_pD3DDevice);
  257.         RELEASE(m_pD3D);
  258.         RELEASE(m_pDD);
  259.     }
  260.  
  261.     CAlphaBlt(LPDIRECTDRAWSURFACE7 lpDDSDst, HRESULT* phr) :
  262.         m_pDD(NULL),
  263.         m_pD3D(NULL),
  264.         m_pD3DDevice(NULL),
  265.         m_lpDDBackBuffer(NULL),
  266.         m_lpDDMirror(NULL),
  267.         m_lpDDM32(NULL),
  268.         m_lpDDM16(NULL),
  269.         m_fPowerOf2(false),
  270.         m_fSquare(false)
  271.     {
  272.  
  273.         ZeroMemory(&m_ddsdM32, sizeof(m_ddsdM32));
  274.         ZeroMemory(&m_ddsdM16, sizeof(m_ddsdM16));
  275.  
  276.         HRESULT hr;
  277.         hr = lpDDSDst->GetDDInterface((LPVOID *)&m_pDD);
  278.         if (FAILED(hr)) {
  279.             m_pDD = NULL;
  280.             *phr = hr;
  281.         }
  282.  
  283.         if (SUCCEEDED(hr)) {
  284.             hr = m_pDD->QueryInterface(IID_IDirect3D7, (LPVOID *)&m_pD3D);
  285.             if (FAILED(hr)) {
  286.                 m_pD3D = NULL;
  287.                 *phr = hr;
  288.             }
  289.         }
  290.  
  291.         if (SUCCEEDED(hr)) {
  292.             hr = m_pD3D->CreateDevice(IID_IDirect3DHALDevice,
  293.                                       lpDDSDst,
  294.                                       &m_pD3DDevice);
  295.             if (FAILED(hr)) {
  296.                 m_pD3DDevice = NULL;
  297.                 *phr = hr;
  298.             }
  299.             else {
  300.                 m_lpDDBackBuffer = lpDDSDst;
  301.                 m_lpDDBackBuffer->AddRef();
  302.             }
  303.         }
  304.  
  305.         if (SUCCEEDED(hr)) {
  306.  
  307.             D3DDEVICEDESC7 ddDesc;
  308.             if (DD_OK == m_pD3DDevice->GetCaps(&ddDesc)) {
  309.  
  310.                 if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) {
  311.                     m_fPowerOf2 = true;
  312.                 }
  313.  
  314.                 if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
  315.                     m_fSquare = true;
  316.                 }
  317.             }
  318.             else {
  319.                 *phr = hr;
  320.             }
  321.         }
  322.     }
  323.  
  324.     HRESULT
  325.     AlphaBlt(RECT* lpDst,
  326.              LPDIRECTDRAWSURFACE7 lpDDSSrc,
  327.              RECT* lpSrc,
  328.              BYTE  bAlpha
  329.              )
  330.     {
  331.         HRESULT hr=S_OK;
  332.         DDSURFACEDESC2 ddsd;
  333.  
  334.         struct {
  335.             float x, y, z, rhw;
  336.             D3DCOLOR clr;
  337.             float tu, tv;
  338.         } pVertices[4];
  339.  
  340.         __try {
  341.  
  342.             INITDDSTRUCT(ddsd);
  343.             CHECK_HR(hr = lpDDSSrc->GetSurfaceDesc(&ddsd));
  344.  
  345.             if (!IsSurfaceBlendable(ddsd, bAlpha)) {
  346.                 CHECK_HR(hr = MirrorSourceSurface(lpDDSSrc, ddsd));
  347.                 lpDDSSrc = m_lpDDMirror;
  348.             }
  349.  
  350.             float fWid = (float)ddsd.dwWidth;
  351.             float fHgt = (float)ddsd.dwHeight;
  352.  
  353.             BYTE alpha = bAlpha;
  354.  
  355.             //
  356.             // Setup the DST info
  357.             //
  358.             pVertices[0].x = (float)lpDst->left;
  359.             pVertices[0].y = (float)lpDst->top;
  360.             pVertices[0].z = 0.5f;
  361.             pVertices[0].rhw = 2.0f;
  362.             pVertices[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  363.  
  364.             pVertices[1].x = (float)lpDst->right;
  365.             pVertices[1].y = (float)lpDst->top;
  366.             pVertices[1].z = 0.5f;
  367.             pVertices[1].rhw = 2.0f;
  368.             pVertices[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  369.  
  370.             pVertices[2].x = (float)lpDst->left;
  371.             pVertices[2].y = (float)lpDst->bottom;
  372.             pVertices[2].z = 0.5f;
  373.             pVertices[2].rhw = 2.0f;
  374.             pVertices[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  375.  
  376.             pVertices[3].x = (float)lpDst->right;
  377.             pVertices[3].y = (float)lpDst->bottom;
  378.             pVertices[3].z = 0.5f;
  379.             pVertices[3].rhw = 2.0f;
  380.             pVertices[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
  381.  
  382.             //
  383.             // Setup the SRC info
  384.             //
  385.             pVertices[0].tu = (float)lpSrc->left / fWid;
  386.             pVertices[0].tv = (float)lpSrc->top / fHgt;
  387.  
  388.             pVertices[1].tu = (float)lpSrc->right / fWid;
  389.             pVertices[1].tv = (float)lpSrc->top / fHgt;
  390.  
  391.             pVertices[2].tu = (float)lpSrc->left / fWid;
  392.             pVertices[2].tv = (float)lpSrc->bottom / fHgt;
  393.  
  394.             pVertices[3].tu = (float)lpSrc->right / fWid;
  395.             pVertices[3].tv = (float)lpSrc->bottom / fHgt;
  396.  
  397.             //
  398.             // Setup some random D3D stuff
  399.             //
  400.             m_pD3DDevice->SetTexture(0, lpDDSSrc);
  401.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
  402.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
  403.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE);
  404.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
  405.             m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
  406.  
  407.             // use diffuse alpha from vertices, not texture alpha
  408.             // m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  409.             m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  410.  
  411.             m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  412.             m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
  413.             m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
  414.             m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
  415.             m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  416.  
  417.             m_pD3DDevice->SetTextureStageState( 0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
  418.  
  419.             //
  420.             // Do the alpha BLT
  421.             //
  422.             CHECK_HR(hr = m_pD3DDevice->BeginScene());
  423.             CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
  424.                                                     D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
  425.                                                     pVertices, 4, D3DDP_WAIT));
  426.             CHECK_HR(hr = m_pD3DDevice->EndScene());
  427.  
  428.         } __finally {
  429.             m_pD3DDevice->SetTexture(0, NULL);
  430.         }
  431.  
  432.         return hr;
  433.     }
  434.  
  435.     bool TextureSquare() {
  436.         return  m_fSquare;
  437.     }
  438.  
  439.     bool TexturePower2() {
  440.         return  m_fPowerOf2;
  441.     }
  442. };
  443.